package com.sandking.io;

import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public class BSON {
	private static final void _writeByte(OutputStream os, byte v)
			throws IOException {
		os.write(v);
	}

	public static final void writeByte(OutputStream os, byte v)
			throws IOException {
		switch (v) {
		case SK_BuffType.BYTE_0:
			_writeByte(os, SK_BuffType.BYTE_0);
			break;
		case SK_BuffType.BYTE_1:
			_writeByte(os, SK_BuffType.BYTE_1);
			break;
		case SK_BuffType.BYTE_2:
			_writeByte(os, SK_BuffType.BYTE_2);
			break;
		case SK_BuffType.BYTE_3:
			_writeByte(os, SK_BuffType.BYTE_3);
			break;
		case SK_BuffType.BYTE_4:
			_writeByte(os, SK_BuffType.BYTE_4);
			break;
		case SK_BuffType.BYTE_5:
			_writeByte(os, SK_BuffType.BYTE_5);
			break;
		case SK_BuffType.BYTE_6:
			_writeByte(os, SK_BuffType.BYTE_6);
			break;
		case SK_BuffType.BYTE_7:
			_writeByte(os, SK_BuffType.BYTE_7);
			break;
		case SK_BuffType.BYTE_8:
			_writeByte(os, SK_BuffType.BYTE_8);
			break;
		case SK_BuffType.BYTE_9:
			_writeByte(os, SK_BuffType.BYTE_9);
			break;
		case SK_BuffType.BYTE_10:
			_writeByte(os, SK_BuffType.BYTE_10);
			break;
		default:
			_writeByte(os, SK_BuffType.BYTE);
			_writeByte(os, v);
			break;
		}

	}

	public static final void writeShort(OutputStream os, short v)
			throws IOException {
		if (v >= SK_BuffType.BYTE_MIN_VALUE && v <= SK_BuffType.BYTE_MAX_VALUE) {
			writeByte(os, (byte) v);
		} else {
			_writeByte(os, SK_BuffType.SHORT);
			_writeByte(os, (byte) ((v >> 8) & 0xff));
			_writeByte(os, (byte) ((v >> 0) & 0xff));
		}
	}

	public static final void writeInt(OutputStream os, int v)
			throws IOException {
		if (v >= SK_BuffType.SHORT_MIN_VALUE && v <= SK_BuffType.SHORT_MAX_VALUE) {
			writeShort(os, (short) v);
		} else {
			_writeByte(os, SK_BuffType.INT);
			_writeByte(os, (byte) ((v >> 24) & 0xff));
			_writeByte(os, (byte) ((v >> 16) & 0xff));
			_writeByte(os, (byte) ((v >> 8) & 0xff));
			_writeByte(os, (byte) ((v >> 0) & 0xff));
		}
	}

	public static final void writeLong(OutputStream os, long v)
			throws IOException {
		if (v >= SK_BuffType.INT_MIN_VALUE && v <= SK_BuffType.INT_MAX_VALUE) {
			writeInt(os, (int) v);
		} else {
			_writeByte(os, SK_BuffType.LONG);
			_writeByte(os, (byte) ((v >> 56) & 0xff));
			_writeByte(os, (byte) ((v >> 48) & 0xff));
			_writeByte(os, (byte) ((v >> 40) & 0xff));
			_writeByte(os, (byte) ((v >> 32) & 0xff));
			_writeByte(os, (byte) ((v >> 24) & 0xff));
			_writeByte(os, (byte) ((v >> 16) & 0xff));
			_writeByte(os, (byte) ((v >> 8) & 0xff));
			_writeByte(os, (byte) ((v >> 0) & 0xff));
		}
	}

	public static final void writeFloat(OutputStream os, float v)
			throws IOException {
		_writeByte(os, SK_BuffType.FLOAT);
		int _v = Float.floatToIntBits(v);
		_writeByte(os, (byte) ((_v >> 24) & 0xff));
		_writeByte(os, (byte) ((_v >> 16) & 0xff));
		_writeByte(os, (byte) ((_v >> 8) & 0xff));
		_writeByte(os, (byte) ((_v >> 0) & 0xff));
	}

	public static final void writeDouble(OutputStream os, double v)
			throws IOException {
		if (v >= SK_BuffType.FLOAT_MIN_VALUE && v <= SK_BuffType.FLOAT_MAX_VALUE) {
			writeFloat(os, (float) v);
		} else {
			_writeByte(os, SK_BuffType.DOUBLE);
			long _v = Double.doubleToLongBits(v);
			_writeByte(os, (byte) ((_v >> 56) & 0xff));
			_writeByte(os, (byte) ((_v >> 48) & 0xff));
			_writeByte(os, (byte) ((_v >> 40) & 0xff));
			_writeByte(os, (byte) ((_v >> 32) & 0xff));
			_writeByte(os, (byte) ((_v >> 24) & 0xff));
			_writeByte(os, (byte) ((_v >> 16) & 0xff));
			_writeByte(os, (byte) ((_v >> 8) & 0xff));
			_writeByte(os, (byte) ((_v >> 0) & 0xff));
		}
	}

	public static final void writeBoolean(OutputStream os, boolean v)
			throws IOException {
		_writeByte(os, v ? SK_BuffType.BOOLEAN_TRUE : SK_BuffType.BOOLEAN_FALSE);
	}

	public static final void writeString(OutputStream os, String v)
			throws Exception {
		byte[] _byte = v.getBytes(SK_BuffType.UTF8);
		int l = _byte.length;
		int _l = (SK_BuffType.STRING_1 - 1) + l;
		switch (_l) {
		case SK_BuffType.STRING_1:
			_writeByte(os, SK_BuffType.STRING_1);
			os.write(_byte);
			break;
		case SK_BuffType.STRING_2:
			_writeByte(os, SK_BuffType.STRING_2);
			os.write(_byte);
			break;
		case SK_BuffType.STRING_3:
			_writeByte(os, SK_BuffType.STRING_3);
			os.write(_byte);
			break;
		case SK_BuffType.STRING_4:
			_writeByte(os, SK_BuffType.STRING_4);
			os.write(_byte);
			break;
		case SK_BuffType.STRING_5:
			_writeByte(os, SK_BuffType.STRING_5);
			os.write(_byte);
			break;
		case SK_BuffType.STRING_6:
			_writeByte(os, SK_BuffType.STRING_6);
			os.write(_byte);
			break;
		case SK_BuffType.STRING_7:
			_writeByte(os, SK_BuffType.STRING_7);
			os.write(_byte);
			break;
		case SK_BuffType.STRING_8:
			_writeByte(os, SK_BuffType.STRING_8);
			os.write(_byte);
			break;
		case SK_BuffType.STRING_9:
			_writeByte(os, SK_BuffType.STRING_9);
			os.write(_byte);
			break;
		case SK_BuffType.STRING_10:
			_writeByte(os, SK_BuffType.STRING_10);
			os.write(_byte);
			break;
		default:
			_writeByte(os, SK_BuffType.STRING);
			writeByteArray(os,_byte);
			break;
		}
	}

	public static final void writeDate(OutputStream os, Date date)
			throws IOException {
		long v = date.getTime();
		_writeByte(os, SK_BuffType.DATE);
		_writeByte(os, (byte) ((v >> 56) & 0xff));
		_writeByte(os, (byte) ((v >> 48) & 0xff));
		_writeByte(os, (byte) ((v >> 40) & 0xff));
		_writeByte(os, (byte) ((v >> 32) & 0xff));
		_writeByte(os, (byte) ((v >> 24) & 0xff));
		_writeByte(os, (byte) ((v >> 16) & 0xff));
		_writeByte(os, (byte) ((v >> 8) & 0xff));
		_writeByte(os, (byte) ((v >> 0) & 0xff));
	}

	public static final void writeByteArray(OutputStream os, byte[] v)
			throws IOException {
		int l = v.length;
		int _l = (SK_BuffType.BYTE_ARRAY_1 - 1) + l;
		switch (_l) {
		case SK_BuffType.BYTE_ARRAY_1:
			_writeByte(os, SK_BuffType.BYTE_ARRAY_1);
			break;
		case SK_BuffType.BYTE_ARRAY_2:
			_writeByte(os, SK_BuffType.BYTE_ARRAY_2);
			break;
		case SK_BuffType.BYTE_ARRAY_3:
			_writeByte(os, SK_BuffType.BYTE_ARRAY_3);
			break;
		case SK_BuffType.BYTE_ARRAY_4:
			_writeByte(os, SK_BuffType.BYTE_ARRAY_4);
			break;
		case SK_BuffType.BYTE_ARRAY_5:
			_writeByte(os, SK_BuffType.BYTE_ARRAY_5);
			break;
		case SK_BuffType.BYTE_ARRAY_6:
			_writeByte(os, SK_BuffType.BYTE_ARRAY_6);
			break;
		case SK_BuffType.BYTE_ARRAY_7:
			_writeByte(os, SK_BuffType.BYTE_ARRAY_7);
			break;
		case SK_BuffType.BYTE_ARRAY_8:
			_writeByte(os, SK_BuffType.BYTE_ARRAY_8);
			break;
		case SK_BuffType.BYTE_ARRAY_9:
			_writeByte(os, SK_BuffType.BYTE_ARRAY_9);
			break;
		case SK_BuffType.BYTE_ARRAY_10:
			_writeByte(os, SK_BuffType.BYTE_ARRAY_10);
			break;
		default:
			_writeByte(os, SK_BuffType.BYTE_ARRAY);
			writeInt(os, v.length);
			break;
		}
		os.write(v);
	}

	public static final void writeShortArray(OutputStream os, short[] v)
			throws IOException {
		_writeByte(os, SK_BuffType.SHORT_ARRAY);
		writeInt(os, v.length);
		for (int i = 0; i < v.length; i++) {
			writeShort(os, v[i]);
		}
	}

	public static final void writeIntArray(OutputStream os, int[] v)
			throws IOException {
		_writeByte(os, SK_BuffType.INT_ARRAY);
		writeInt(os, v.length);
		for (int i = 0; i < v.length; i++) {
			writeInt(os, v[i]);
		}
	}

	public static final void writeLongArray(OutputStream os, long[] v)
			throws IOException {
		_writeByte(os, SK_BuffType.LONG_ARRAY);
		writeInt(os, v.length);
		for (int i = 0; i < v.length; i++) {
			writeLong(os, v[i]);
		}
	}

	public static final void writeFloatArray(OutputStream os, float[] v)
			throws IOException {
		_writeByte(os, SK_BuffType.FLOAT_ARRAY);
		writeInt(os, v.length);
		for (int i = 0; i < v.length; i++) {
			writeFloat(os, v[i]);
		}
	}

	public static final void writeDoubleArray(OutputStream os, double[] v)
			throws IOException {
		_writeByte(os, SK_BuffType.DOUBLE_ARRAY);
		writeInt(os, v.length);
		for (int i = 0; i < v.length; i++) {
			writeDouble(os, v[i]);
		}
	}

	public static final void writeBooleanArray(OutputStream os, boolean[] v)
			throws IOException {
		_writeByte(os, SK_BuffType.BOOLEAN_ARRAY);
		writeInt(os, v.length);
		for (int i = 0; i < v.length; i++) {
			writeBoolean(os, v[i]);
		}
	}

	public static final void writeStringArray(OutputStream os, String[] v)
			throws Exception {
		_writeByte(os, SK_BuffType.STRING_ARRAY);
		writeInt(os, v.length);
		for (int i = 0; i < v.length; i++) {
			writeString(os, v[i]);
		}
	}

	public static final void writeDateArray(OutputStream os, Date[] v)
			throws Exception {
		_writeByte(os, SK_BuffType.DATE_ARRAY);
		writeInt(os, v.length);
		for (int i = 0; i < v.length; i++) {
			writeDate(os, v[i]);
		}
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static final void writeMap(OutputStream os, Map map)
			throws Exception {
		_writeByte(os, SK_BuffType.MAP);
		writeInt(os, map.size());
		Set<Entry> entrys = map.entrySet();
		for (Map.Entry entry : entrys) {
			writeObject(os, entry.getKey());
			writeObject(os, entry.getValue());
		}
	}

	public static final void writeList(OutputStream os, List<Object> list)
			throws Exception {
		_writeByte(os, SK_BuffType.LIST);
		writeInt(os, list.size());
		for (Object object : list) {
			writeObject(os, object);
		}
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static final void writeObject(OutputStream os, Object obj)
			throws Exception {
		if (obj instanceof Byte) {
			writeByte(os, (byte) obj);
		} else if (obj instanceof Short) {
			writeShort(os, (short) obj);
		} else if (obj instanceof Integer) {
			writeInt(os, (int) obj);
		} else if (obj instanceof Long) {
			writeLong(os, (long) obj);
		} else if (obj instanceof Float) {
			writeFloat(os, (float) obj);
		} else if (obj instanceof Double) {
			writeDouble(os, (double) obj);
		} else if (obj instanceof Boolean) {
			writeBoolean(os, (boolean) obj);
		} else if (obj instanceof String) {
			writeString(os, (String) obj);
		} else if (obj instanceof Date) {
			writeDate(os, (Date) obj);
		} else if (obj instanceof Byte[] || obj instanceof byte[]) {
			writeByteArray(os, (byte[]) obj);
		} else if (obj instanceof Short[] || obj instanceof short[]) {
			writeShortArray(os, (short[]) obj);
		} else if (obj instanceof Integer[] || obj instanceof int[]) {
			writeIntArray(os, (int[]) obj);
		} else if (obj instanceof Long[] || obj instanceof long[]) {
			writeLongArray(os, (long[]) obj);
		} else if (obj instanceof Float[] || obj instanceof float[]) {
			writeFloatArray(os, (float[]) obj);
		} else if (obj instanceof Double[] || obj instanceof double[]) {
			writeDoubleArray(os, (double[]) obj);
		} else if (obj instanceof Boolean[] || obj instanceof boolean[]) {
			writeBooleanArray(os, (boolean[]) obj);
		} else if (obj instanceof String[]) {
			writeStringArray(os, (String[]) obj);
		} else if (obj instanceof Date[]) {
			writeDateArray(os, (Date[]) obj);
		} else if (obj instanceof Map) {
			writeMap(os, (Map) obj);
		} else if (obj instanceof List) {
			writeList(os, (List<Object>) obj);
		}
	}

	// -------------------------------------------------read
	private static final byte _readByte(InputStream in) throws IOException {
		int ch = in.read();
		if (ch < 0)
			throw new EOFException();
		return (byte) (ch);
	}

	public static final byte readByte(InputStream in, Byte type)
			throws IOException {
		if (type == null)
			type = _readByte(in);
		switch (type) {
		case SK_BuffType.BYTE_0:
		case SK_BuffType.BYTE_1:
		case SK_BuffType.BYTE_2:
		case SK_BuffType.BYTE_3:
		case SK_BuffType.BYTE_4:
		case SK_BuffType.BYTE_5:
		case SK_BuffType.BYTE_6:
		case SK_BuffType.BYTE_7:
		case SK_BuffType.BYTE_8:
		case SK_BuffType.BYTE_9:
		case SK_BuffType.BYTE_10:
			return type;
		case SK_BuffType.BYTE:
			return _readByte(in);
		default:
			throw new EOFException();
		}
	}

	public static final short readShort(InputStream in, Byte type)
			throws IOException {
		if (type == null)
			type = _readByte(in);
		if (type == SK_BuffType.SHORT) {
			int _v;
			_v = ((_readByte(in) & 0xff) << 8);
			_v += ((_readByte(in) & 0xff) << 0);
			short v = (short) (_v);
			return v;
		} else {
			return readByte(in, type);
		}
	}

	public static final int readInt(InputStream in, Byte type)
			throws IOException {
		if (type == null)
			type = _readByte(in);
		if (type == SK_BuffType.INT) {
			int _v;
			_v = ((_readByte(in) & 0xff) << 24);
			_v += ((_readByte(in) & 0xff) << 16);
			_v += ((_readByte(in) & 0xff) << 8);
			_v += ((_readByte(in) & 0xff) << 0);
			return _v;
		} else {
			return readShort(in, type);
		}
	}

	public static final long readLong(InputStream in, Byte type)
			throws IOException {
		if (type == null)
			type = _readByte(in);
		if (type == SK_BuffType.LONG) {
			long high;
			high = ((_readByte(in) & 0xff) << 24);
			high += ((_readByte(in) & 0xff) << 16);
			high += ((_readByte(in) & 0xff) << 8);
			high += ((_readByte(in) & 0xff) << 0);
			long low;
			low = ((_readByte(in) & 0xff) << 24);
			low += ((_readByte(in) & 0xff) << 16);
			low += ((_readByte(in) & 0xff) << 8);
			low += ((_readByte(in) & 0xff) << 0);
			long v = (high << 32) + (0xffffffffL & low);
			return v;
		} else {
			return readInt(in, type);
		}
	}

	public static final float readFloat(InputStream in, Byte type)
			throws IOException {
		if (type == null)
			type = _readByte(in);
		if (type == SK_BuffType.FLOAT) {
			int _v;
			_v = ((_readByte(in) & 0xff) << 24);
			_v += ((_readByte(in) & 0xff) << 16);
			_v += ((_readByte(in) & 0xff) << 8);
			_v += ((_readByte(in) & 0xff) << 0);
			return Float.intBitsToFloat(_v);
		}
		throw new EOFException();
	}

	public static final double readDouble(InputStream in, Byte type)
			throws IOException {
		if (type == null)
			type = _readByte(in);
		if (type == SK_BuffType.DOUBLE) {
			long high;
			high = ((_readByte(in) & 0xff) << 56);
			high += ((_readByte(in) & 0xff) << 48);
			high += ((_readByte(in) & 0xff) << 40);
			high += ((_readByte(in) & 0xff) << 32);
			long low;
			low = ((_readByte(in) & 0xff) << 24);
			low += ((_readByte(in) & 0xff) << 16);
			low += ((_readByte(in) & 0xff) << 8);
			low += ((_readByte(in) & 0xff) << 0);
			long _v = (high << 32) + (0xffffffffL & low);
			return Double.longBitsToDouble(_v);
		} else {
			return readFloat(in, type);
		}
	}

	public static final boolean readBoolean(InputStream in, Byte type)
			throws IOException {
		if (type == null)
			type = _readByte(in);
		switch (type) {
		case SK_BuffType.BOOLEAN_TRUE:
			return true;
		case SK_BuffType.BOOLEAN_FALSE:
			return false;
		default:
			throw new EOFException();
		}
	}

	public static final String readString(InputStream in, Byte type)
			throws Exception {
		if (type == null)
			type = _readByte(in);
		switch (type) {
		case SK_BuffType.STRING_1:
		case SK_BuffType.STRING_2:
		case SK_BuffType.STRING_3:
		case SK_BuffType.STRING_4:
		case SK_BuffType.STRING_5:
		case SK_BuffType.STRING_6:
		case SK_BuffType.STRING_7:
		case SK_BuffType.STRING_8:
		case SK_BuffType.STRING_9:
		case SK_BuffType.STRING_10:
			int l = type + 1 - SK_BuffType.STRING_1;
			byte[] b = new byte[l];
			in.read(b, 0, l);
			return new String(b, SK_BuffType.UTF8);
		default:
			return new String(readByteArray(in, null), SK_BuffType.UTF8);
		}
	}

	public static final Date readDate(InputStream in, Byte type)
			throws Exception {
		if (type == null)
			type = _readByte(in);
		if (type == SK_BuffType.DATE) {
			return new Date(readLong(in, SK_BuffType.LONG));
		}
		throw new EOFException();
	}

	public static final byte[] readByteArray(InputStream in, Byte type)
			throws IOException {
		int l = 0;
		if (type == null)
			type = _readByte(in);
		switch (type) {
		case SK_BuffType.BYTE_ARRAY_1:
		case SK_BuffType.BYTE_ARRAY_2:
		case SK_BuffType.BYTE_ARRAY_3:
		case SK_BuffType.BYTE_ARRAY_4:
		case SK_BuffType.BYTE_ARRAY_5:
		case SK_BuffType.BYTE_ARRAY_6:
		case SK_BuffType.BYTE_ARRAY_7:
		case SK_BuffType.BYTE_ARRAY_8:
		case SK_BuffType.BYTE_ARRAY_9:
		case SK_BuffType.BYTE_ARRAY_10:
			l = type + 1 - SK_BuffType.BYTE_ARRAY_1;
			break;
		default:
			l = readInt(in, null);
			break;
		}
		byte[] b = new byte[l];
		in.read(b, 0, l);
		return b;
	}

	public static final short[] readShortArray(InputStream in, Byte type)
			throws IOException {
		if (type == null)
			type = _readByte(in);
		int l = readInt(in, null);
		short[] b = new short[l];
		for (int i = 0; i < b.length; i++) {
			b[i] = readShort(in, null);
		}
		return b;
	}

	public static final int[] readIntArray(InputStream in, Byte type)
			throws IOException {
		if (type == null)
			type = _readByte(in);
		int l = readInt(in, null);
		int[] b = new int[l];
		for (int i = 0; i < b.length; i++) {
			b[i] = readInt(in, null);
		}
		return b;
	}

	public static final long[] readLongArray(InputStream in, Byte type)
			throws IOException {
		if (type == null)
			type = _readByte(in);
		int l = readInt(in, null);
		long[] b = new long[l];
		for (int i = 0; i < b.length; i++) {
			b[i] = readLong(in, null);
		}
		return b;
	}

	public static final float[] readFloatArray(InputStream in, Byte type)
			throws IOException {
		if (type == null)
			type = _readByte(in);
		int l = readInt(in, null);
		float[] b = new float[l];
		for (int i = 0; i < b.length; i++) {
			b[i] = readFloat(in, null);
		}
		return b;
	}

	public static final double[] readDoubleArray(InputStream in, Byte type)
			throws IOException {
		if (type == null)
			type = _readByte(in);
		int l = readInt(in, null);
		double[] b = new double[l];
		for (int i = 0; i < b.length; i++) {
			b[i] = readDouble(in, null);
		}
		return b;
	}

	public static final boolean[] readBooleanArray(InputStream in, Byte type)
			throws IOException {
		if (type == null)
			type = _readByte(in);
		int l = readInt(in, null);
		boolean[] b = new boolean[l];
		for (int i = 0; i < b.length; i++) {
			b[i] = _readByte(in) == SK_BuffType.BOOLEAN_TRUE;
		}
		return b;
	}

	public static final String[] readStringArray(InputStream in, Byte type)
			throws Exception {
		if (type == null)
			type = _readByte(in);
		int l = readInt(in, null);
		String[] b = new String[l];
		for (int i = 0; i < b.length; i++) {
			b[i] = readString(in, null);
		}
		return b;
	}

	public static final Date[] readDateArray(InputStream in, Byte type)
			throws Exception {
		if (type == null)
			type = _readByte(in);
		int l = readInt(in, null);
		Date[] b = new Date[l];
		for (int i = 0; i < b.length; i++) {
			b[i] = readDate(in, null);
		}
		return b;
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static final Map readMap(InputStream in, Byte type)
			throws Exception {
		if (type == null)
			type = _readByte(in);
		int l = readInt(in, null);
		Map map = new HashMap();
		for (int i = 0; i < l; i++) {
			map.put(readObject(in), readObject(in));
		}
		return map;
	}

	public static final List<Object> readList(InputStream in, Byte type)
			throws Exception {
		if (type == null)
			type = _readByte(in);
		int l = readInt(in, null);
		List<Object> list = new ArrayList<Object>();
		for (int i = 0; i < l; i++) {
			list.add(readObject(in));
		}
		return list;
	}

	public static final Object readObject(InputStream in) throws Exception {
		byte type = _readByte(in);
		switch (type) {
		case SK_BuffType.BYTE:
		case SK_BuffType.BYTE_0:
		case SK_BuffType.BYTE_1:
		case SK_BuffType.BYTE_2:
		case SK_BuffType.BYTE_3:
		case SK_BuffType.BYTE_4:
		case SK_BuffType.BYTE_5:
		case SK_BuffType.BYTE_6:
		case SK_BuffType.BYTE_7:
		case SK_BuffType.BYTE_8:
		case SK_BuffType.BYTE_9:
		case SK_BuffType.BYTE_10:
			return readByte(in, type);
		case SK_BuffType.SHORT:
			return readShort(in, type);
		case SK_BuffType.INT:
			return readInt(in, type);
		case SK_BuffType.LONG:
			return readLong(in, type);
		case SK_BuffType.FLOAT:
			return readFloat(in, type);
		case SK_BuffType.DOUBLE:
			return readDouble(in, type);
		case SK_BuffType.STRING:
		case SK_BuffType.STRING_1:
		case SK_BuffType.STRING_2:
		case SK_BuffType.STRING_3:
		case SK_BuffType.STRING_4:
		case SK_BuffType.STRING_5:
		case SK_BuffType.STRING_6:
		case SK_BuffType.STRING_7:
		case SK_BuffType.STRING_8:
		case SK_BuffType.STRING_9:
		case SK_BuffType.STRING_10:
			return readString(in, type);
		case SK_BuffType.DATE:
			return readDate(in, type);
		case SK_BuffType.BYTE_ARRAY:
		case SK_BuffType.BYTE_ARRAY_1:
		case SK_BuffType.BYTE_ARRAY_2:
		case SK_BuffType.BYTE_ARRAY_3:
		case SK_BuffType.BYTE_ARRAY_4:
		case SK_BuffType.BYTE_ARRAY_5:
		case SK_BuffType.BYTE_ARRAY_6:
		case SK_BuffType.BYTE_ARRAY_7:
		case SK_BuffType.BYTE_ARRAY_8:
		case SK_BuffType.BYTE_ARRAY_9:
		case SK_BuffType.BYTE_ARRAY_10:
			return readByteArray(in, type);
		case SK_BuffType.SHORT_ARRAY:
			return readShortArray(in, type);
		case SK_BuffType.INT_ARRAY:
			return readIntArray(in, type);
		case SK_BuffType.LONG_ARRAY:
			return readLongArray(in, type);
		case SK_BuffType.FLOAT_ARRAY:
			return readFloatArray(in, type);
		case SK_BuffType.DOUBLE_ARRAY:
			return readDouble(in, type);
		case SK_BuffType.BOOLEAN_ARRAY:
			return readBooleanArray(in, type);
		case SK_BuffType.STRING_ARRAY:
			return readStringArray(in, type);
		case SK_BuffType.DATE_ARRAY:
			return readDateArray(in, type);
		case SK_BuffType.MAP:
			return readMap(in, type);
		case SK_BuffType.LIST:
			return readList(in, type);
		case SK_BuffType.BOOLEAN_TRUE:
			return true;
		case SK_BuffType.BOOLEAN_FALSE:
			return false;
		default:
			throw new EOFException();
		}
	}
}
